package cn.ilikes.tools.nosql.jpa.persistences.contexts.operations;

import java.util.LinkedList;
import java.util.Queue;

import cn.ilikes.tools.nosql.jpa.clients.Client;
import cn.ilikes.tools.nosql.jpa.clients.JPASQLClientsException;
import cn.ilikes.tools.nosql.jpa.graphs.INodeBuilderListener;
import cn.ilikes.tools.nosql.jpa.graphs.INodeGraphBuilder;
import cn.ilikes.tools.nosql.jpa.graphs.Node;
import cn.ilikes.tools.nosql.jpa.graphs.NodeGraphBuilder;
import cn.ilikes.tools.nosql.jpa.graphs.INodeGraphBuilder.BuildType;
import cn.ilikes.tools.nosql.jpa.graphs.Node.State;
import cn.ilikes.tools.nosql.jpa.graphs.NodeLifeCycle.LifeCycle;
import cn.ilikes.tools.nosql.jpa.metadatas.EntityMetaData;
import cn.ilikes.tools.nosql.jpa.persistences.contexts.AbstractContext;
import cn.ilikes.tools.nosql.jpa.persistences.contexts.Operation;
import cn.ilikes.tools.nosql.jpa.persistences.contexts.OperationRunTimeException;

public class RemoveOperation extends ContextOperation implements Operation<Boolean> {

	private Object entity;

	private Queue<Node> stack = new LinkedList<Node>();

	private Queue<Node> delDtack = new LinkedList<Node>();

	public RemoveOperation(AbstractContext context, Object entity) {
		super(OperationType.delete, context);
		this.entity = entity;

	}

	@Override
	public Boolean exec() {

		Client client = getContext().getClient();
		try {
			while (!stack.isEmpty()) {
				Node node = stack.poll();
				client.delete(node);
				Node.switchNodeLifeCycle(node, LifeCycle.removed);
				node.setState(State.remove);
				delDtack.add(node);
			}
			return Boolean.TRUE;
		} catch (JPASQLClientsException e) {
			throw new OperationRunTimeException(e);
		}
	}

	@Override
	public boolean init() {
		if (entity == null)
			throw new OperationRunTimeException("this remove entity  is null ");
		AbstractContext context = getContext();
		INodeGraphBuilder nodeGraphBuilder = new NodeGraphBuilder(context.getPersistenUnitEnv(), new INodeBuilderListener() {
			@Override
			public void buildNode(Node node) {

				stack.add(node);
			}
		});
		EntityMetaData entityMetaData = context.getPersistenUnitEnv().getMetaDataManagerFactory().selectIEntityMetaData(entity.getClass());
		Node node = Node.createtNode(entityMetaData, entity, LifeCycle.newses);
		nodeGraphBuilder.buildNodeStack(node, BuildType.remove);
		return true;
	}

	@Override
	public boolean rollback() {
		Client client = getContext().getClient();
		try {
			while (!delDtack.isEmpty()) {
				Node node = delDtack.poll();
				client.save(node);
				Node.switchNodeLifeCycle(node, LifeCycle.managed);
				node.setState(State.noState);
			}
			return Boolean.TRUE;
		} catch (JPASQLClientsException e) {
			throw new OperationRunTimeException(e);
		}
	}

}
